/** \file Team.cpp
 *  \author Adrian Schweizer
 *  \created  $Sa 18 Aug 03:48:01 pm CEST 2007 schwadri@SchwadriComp.local$
 *  \modified $So 30 Sep 06:22:14 pm CEST 2007 schwadri@SchwadriLaptop$
 */

#include "Team.hpp"
#include "TeamManager.hpp"

using namespace game;

const int Team::LIMIT_TEAM_SIZE   =   4;

Team::Team(TeamManager* team_manager, char tid)
:   m_team_manager(team_manager),
    m_tid(tid)
{
    if(!team_manager)
        throw "Team::Team() Supplied invalid team Manager";
}

Team::~Team()
{
    Clear();
}

void Team::Clear()
{
    foreach(Player & p, m_players)
        if(p.ClientId()!=-1)
            m_team_manager->m_cid_to_pid[p.ClientId()] =   Player::Id::INVALID;

    m_players.clear();
}

void Team::PushBack(const Player& p)
{
    if(m_players.size()>=m_max_players)
        return;
    m_players.push_back(p);

    //fix Player::Id
    Player & player = m_players.back();
    player.TeamId(m_tid);
    player.PlayerIndex(m_players.size()-1);

    //update cid to pid mapping
    if(player.ClientId()!=-1)
        m_team_manager->m_cid_to_pid[player.ClientId()] =   player.PlayerId();
}

void Team::PushBack(network::Client::Id cid)
{
    if(m_players.size()>=m_max_players)
        return;
    m_players.push_back(Player(cid));

    //fix Player::Id
    Player & player = m_players.back();
    player.TeamId(m_tid);
    player.PlayerIndex(m_players.size()-1);
    //update cid to pid mapping
    if(player.ClientId()!=-1)
        m_team_manager->m_cid_to_pid[player.ClientId()] =   player.PlayerId();
}

void Team::TeamId(char tid)
{
    if(m_tid==tid)
        return;
    m_tid   =   tid;
    foreach(Player & p, m_players)
        p.TeamId(tid);
}

void Team::ShiftPlayersIndex(player_iterator piter)
{
    char idx =  piter-m_players.begin();
    for(;piter!=m_players.end();++piter,++idx)
    {
        piter->PlayerIndex(idx);
        if(piter->ClientId()!=-1)
            m_team_manager->m_cid_to_pid[piter->ClientId()] =   piter->PlayerId();
    }
}

void Team::Remove(const Player& player)
{
    if(player.TeamId() != m_tid || player.PlayerIndex() <0 || player.PlayerIndex() >= m_players.size())
        return;

    Remove(m_players.begin() + player.PlayerIndex());
}

void Team::Remove(Player::Id pid)
{
    if(pid.team != m_tid || pid.player <0 || pid.player >= m_players.size())
        return;

    Remove(m_players.begin() + pid.player);
}

void Team::Remove(network::Client::Id cid)
{
    //find player with cid
    for(player_iterator piter=m_players.begin();piter!=m_players.end();++piter)
        if(piter->ClientId()==cid)
        {
            Remove(piter);
            return;
        }
}

Team::player_iterator Team::Remove(player_iterator piter)
{
    {
        Player & player = *piter;
        //update cid to pid mapping
        if(player.ClientId()!=-1)
            m_team_manager->m_cid_to_pid[player.ClientId()] =   player.PlayerId();
    }
    piter = m_players.erase(piter);

    //fix all the player after this player
    ShiftPlayersIndex(piter);
    return piter;
}

void Team::Remove(char pidx)
{
    if(pidx <0 || pidx >= m_players.size())
        return;

    Remove(m_players.begin() + pidx);
}
